/*
 * @Author: szx
 * @Date: 2022-03-11 19:28:10
 * @LastEditTime: 2022-03-11 21:46:22
 * @Description:
 * @FilePath: \MDN_JS学习\手撸JS源码\_Promise3.js
 */
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

function _Promise(executor) {
    const _this = this;
    this.status = PENDING; //状态
    this.result = undefined; //成功结果
    this.onFulfilled = []; //成功回调函数队列
    this.onRejected = []; //失败回调函数队列
    function resolve(value) {
        if (_this.status === PENDING) {
            // 如果是Promise类型的，那么就转换成异步的
            if (value instanceof _Promise) {
                value.then(
                    (v) => resolve(v),
                    (r) => reject(r)
                );
            } else {
                _this.status = FULFILLED;
                _this.result = value;
                _this.onFulfilled.forEach((fn) => fn(value));
            }
        }
    }
    function reject(reason) {
        if (_this.status === PENDING) {
            _this.status = REJECTED;
            _this.result = reason;
            _this.onRejected.forEach((fn) => fn(reason));
        }
    }
    try {
        executor(resolve, reject);
    } catch (error) {
        console.log('?');
        reject(error);
    }
}

_Promise.prototype.then = function (onFulfilled, onRejected) {
    const _this = this;
    // 检查是不是function，如果不是，就给个默认函数
    if (typeof onFulfilled !== 'function') onFulfilled = (value) => value;
    if (typeof onRejected !== 'function')
        onRejected = (reason) => {
            throw reason;
        };
    // 为了能够链式调用then，返回值一定要是_Promise的
    return new _Promise((resolve, reject) => {
        /**
         * 执行onFulfilled(value)和onRejected(reason),得到下一个结果
         * @param {onFulfilled|onRejected} callback
         * @param {any} result
         */
        function handle(callback, result) {
            try {
                const nextResult = callback(result);
                // 如果还是_Promise类型的
                if (nextResult instanceof _Promise) {
                    // 那么等nextRusult执行完成了，再把结果赋值给resolve
                    nextResult.then(
                        (v) => resolve(v),
                        (r) => reject(r)
                    );
                } else {
                    resolve(nextResult);
                }
            } catch (err) {
                reject(err);
            }
        }

        if (_this.status === FULFILLED) {
            /* 状态已经完成了，比如这种直接返回的情况
                Promise((resolve, reject) => {
                    resolve(3);
                }).then();
                虽然已经成功了，但是也不能直接主线程返回值，要通过异步的方式返回值（原生Promise就是这样的）
            */
            setTimeout(() => {
                handle(onFulfilled, _this.result);
            });
        } else if (_this.status === REJECTED) {
            setTimeout(() => {
                handle(onRejected, _this.result);
            });
        } else {
            // 主线程如果还在Pending，那么就先把回调函数放到队列里面
            // 等到主线程运行完，开始运行Promise里面的异步函数
            // 就会执行resolve/reject，从而调用队列里面的函数
            _this.onFulfilled.push(() => {
                handle(onFulfilled, _this.result);
            });
            _this.onRejected.push(() => {
                handle(onRejected, _this.result);
            });
        }
    });
};

// 实例方法catch
_Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected);
};

// 实例方法finally
_Promise.prototype.finally = function (onFinally) {
    return this.then(onFinally, onFinally);
};

// 静态方法resolve
_Promise.resolve = function (value) {
    return new _Promise((resolve, reject) => {
        resolve(value);
    });
};

//静态方法resolve
_Promise.reject = function (reason) {
    return new _Promise((resolve, reject) => {
        reject(reason);
    });
};

// console.log('开始');

// const p = new _Promise((resolve, reject) => {
//     console.log('输入');
//     setTimeout(function () {
//         resolve(1);
//     }, 1000);
// });
// p.then(
//     (value) => {
//         console.log('1', value);
//         return 2;
//     },
//     (err) => {
//         console.log('err1', err);
//     }
// )
//     .then((value) => {
//         console.log('2', value);
//         throw 'wrong!';
//     })
//     .catch((err) => {
//         console.log('err2', err);
//     });

// console.log('结束');

var p1 = new _Promise((resolve, reject) => {
    resolve('p1');
});
p1.then((res) => {
    console.log(res);
    return new _Promise((resolve, reject) => {
        resolve(
            new _Promise((resolve, reject) => {
                resolve('p2');
            })
        );
    });
}).then((res1) => {
    console.log(res1);
});